#import "BWStitchEditController.h"
#import "BWStitchEditCanvas.h"
#import "BWSymbol.h"


NSString *BWStitchEditController_ClosedNotification
= @"BWStitchEditController Closed Notification";

NSString *BWStitchEditController_ChangeNotification
= @"BWStitchEditController Change Notification";


@implementation  BWStitchEditController

- (id) initWithRawPath: (BWSymbol *) thePath;
{
    self = [super initWithWindowNibName: @"StitchEditWindow"
                  owner: self];

    rawPath = [thePath retain];

    return (self);

} // init

- (void) dealloc
{
    [rawPath release];
    [super dealloc];

} // dealloc


- (BWSymbol *) rawPath
{
    return (rawPath);

} // rawPath


- (void) awakeFromNib
{
    [stitchCanvas setRawPath: rawPath];
    [nameField setStringValue: [rawPath name]];
    [keywordsField setStringValue: [rawPath keywords]];
    [symbolIdField setIntValue: [rawPath symbolId]];

    [stitchCanvas setCurveToggleState:
                      [curveToggleCheckbox state] == NSOnState];
    [stitchCanvas setControlPointToggleState:
                      [curveToggleCheckbox state] == NSOnState];

} // awakeFromNib


- (void) addNewPoint: (NSPoint) point  atIndex: (int) index
{
    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    [[undoManager prepareWithInvocationTarget: self]
        removePoint: index];

    [rawPath addElement: NSLineToBezierPathElement
             atIndex: index
             associatedPoints: &point];
    [stitchCanvas setNeedsDisplay: YES];
    
    [[NSNotificationCenter defaultCenter]
        postNotificationName: BWStitchEditController_ChangeNotification
        object: self];

} // addNewPoint



// points are passed in explictly so that the undo manager
// can capture their values.  passing an array address on the
// stack Just Won't Work

- (void) addNewCurve: (NSPoint) point1
                 pt2: (NSPoint) point2
                 pt3: (NSPoint) point3
             atIndex: (int) index
{
    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    // hack???
    if ([rawPath elementCount] == 0) {
        // if we insert a curve to start out with, we get a zeroth
        // element that is a moveTo point.   The one we'll actually
        // want to nuke is the 1th item.
        [[undoManager prepareWithInvocationTarget: self]
            removePoint: 1];
    } else {
        [[undoManager prepareWithInvocationTarget: self]
            removePoint: index];
    }

    NSPoint points[3];
    points[0] = point1;
    points[1] = point2;
    points[2] = point3;

    [rawPath addElement: NSCurveToBezierPathElement
             atIndex: index
             associatedPoints: points];
    [stitchCanvas setNeedsDisplay: YES];
    

    [[NSNotificationCenter defaultCenter]
        postNotificationName: BWStitchEditController_ChangeNotification
        object: self];

} // addNewCurve


- (void) removePoint: (int) index
{
    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    // figure out the type
    NSPoint points[3];
    NSBezierPathElement type;

    type = [rawPath elementAtIndex: index
                    associatedPoints: points];

    if (type == NSLineToBezierPathElement
        || type == NSMoveToBezierPathElement)  {
        [[undoManager prepareWithInvocationTarget: self]
            addNewPoint: points[0]  atIndex: index];
    } else if (type == NSCurveToBezierPathElement) {
        [[undoManager prepareWithInvocationTarget: self]
            addNewCurve: points[0] pt2: points[1]  pt3: points[2]
            atIndex: index];
    }

    [rawPath removeElementIndex: index];

    [stitchCanvas setNeedsDisplay: YES];

    [[NSNotificationCenter defaultCenter]
        postNotificationName: BWStitchEditController_ChangeNotification
        object: self];

} // removePoint


- (IBAction) addPoint: (id) sender
{
    // where, oh where, to put the new point?
    // for now, put it in the middle
    NSPoint point;
    point = NSMakePoint (0.5, 0.5);

    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    [undoManager setActionName: @"Add Point"];

    [self addNewPoint: point
        atIndex: [rawPath elementCount]];

} // addPoint


- (IBAction) addCurve: (id) sender
{
    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    [undoManager setActionName: @"Add Curve"];

    NSPoint points[3];
    
    points[0] = NSMakePoint (0.25, 0.1);
    points[1] = NSMakePoint (0.75, 0.1);
    points[2] = NSMakePoint (0.5, 0.5);

    [self addNewCurve: points[0]
          pt2: points[1]
          pt3: points[2]
          atIndex: [rawPath elementCount]];


    [stitchCanvas setNeedsDisplay: YES];

    [[NSNotificationCenter defaultCenter]
        postNotificationName: BWStitchEditController_ChangeNotification
        object: self];

} // addCurve


- (IBAction) addPath: (id) sender
{
    NSPoint point;

    point = NSMakePoint (0.5, 0.5);

    [rawPath addElement: NSMoveToBezierPathElement
             atIndex: [rawPath elementCount]
             associatedPoints: &point];

    [stitchCanvas setNeedsDisplay: YES];

    [[NSNotificationCenter defaultCenter]
        postNotificationName: BWStitchEditController_ChangeNotification
        object: self];

} // addPath


- (IBAction) deletePoint: (id) sender
{
    int index;
    index = [stitchCanvas selectedIndex];

    int elementIndex;
    elementIndex = [rawPath elementIndexForPointIndex: index];

    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    [undoManager setActionName: @"Remove Point"];

    [self removePoint: elementIndex];

} // deletePoint



//
// ---- Delegate methods
//

- (void) pointIndex: (int) index  changedToPoint: (NSPoint) point
{
    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    NSPoint oldPoint;
    oldPoint = [rawPath pointAtIndex: index];

    [[undoManager prepareWithInvocationTarget: self]
        pointIndex: index  changedToPoint: oldPoint];
    [undoManager setActionName: @"Move Control Point"];

    [rawPath setPoint: point  atIndex: index];

    [[NSNotificationCenter defaultCenter]
        postNotificationName: BWStitchEditController_ChangeNotification
        object: self];

    [stitchCanvas setNeedsDisplay: YES];

} // pointIndex changedToPoint


- (void) selectedPoint: (int) index
{
    // can't nuke the original move-to

    if (index == -1 || index == 0) {
        [deleteButton setEnabled: NO];
    } else {
        [deleteButton setEnabled: YES];

        int elementIndex;
        elementIndex = [rawPath elementIndexForPointIndex: index];

        NSBezierPathElement type;
        type = [rawPath elementAtIndex: elementIndex
                        associatedPoints: NULL];
        if (type == NSCurveToBezierPathElement) {
            [deleteButton setTitle: @"Remove Curve"];
        } else {
            [deleteButton setTitle: @"Remove Point"];
        }
    }
    
} // selectedPoint


- (IBAction) toggleCurveLines: (id) sender;
{
    [stitchCanvas setCurveToggleState:
                      [sender state] == NSOnState];
    [curveToggleCheckbox setState: [sender state]];

} // toggleCurveLines


- (IBAction) toggleControlPoints: (id) sender;
{
    [stitchCanvas setControlPointToggleState:
                      [sender state] == NSOnState];
    [controlPointCheckbox setState: [sender state]];

} // toggleCurveLines


- (void) changeName: (NSString *) name
{
    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    [[undoManager prepareWithInvocationTarget: self]
        changeName: [rawPath name]];
    [undoManager setActionName: @"Name Change"];

    [rawPath setName: name];

    if ([undoManager isUndoing]
        || [undoManager isRedoing]) {
        [nameField setStringValue: name];
    }

    [[NSNotificationCenter defaultCenter]
        postNotificationName: BWStitchEditController_ChangeNotification
        object: self];

} // changeName


- (IBAction) setName: (id) sender
{
    [self changeName: [nameField stringValue]];

} // setName


- (void) changeKeywords: (NSString *) keywords
{
    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    [[undoManager prepareWithInvocationTarget: self]
        changeKeywords: [rawPath keywords]];
    [undoManager setActionName: @"Keywords Change"];

    [rawPath setKeywords: keywords];

    if ([undoManager isUndoing]
        || [undoManager isRedoing]) {
        [keywordsField setStringValue: keywords];
    }

    [[NSNotificationCenter defaultCenter]
        postNotificationName: BWStitchEditController_ChangeNotification
        object: self];

} // changeKeywords


- (IBAction) setKeywords: (id) sender
{
    [self changeKeywords: [keywordsField stringValue]];

} // setKeywords


- (void) changeSymbolId: (NSNumber *) symbolId
{
    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    [[undoManager prepareWithInvocationTarget: self]
        changeSymbolId: [NSNumber numberWithInt: [rawPath symbolId]]];
    [undoManager setActionName: @"Symbol Id Change"];

    [rawPath setSymbolId: [symbolId intValue]];

    if ([undoManager isUndoing]
        || [undoManager isRedoing]) {
        [symbolIdField setIntValue: [symbolId intValue]];
    }

    [[NSNotificationCenter defaultCenter]
        postNotificationName: BWStitchEditController_ChangeNotification
        object: self];

} // changeSymbolId


- (IBAction) setSymbolId: (id) sender
{
    [self changeSymbolId: [NSNumber numberWithInt: [symbolIdField intValue]]];
} // setSymbolId


- (void) movePathByX: (float) offsetX  Y: (float) offsetY
{
    NSUndoManager *undoManager;
    undoManager = [[self document] undoManager];

    [[undoManager prepareWithInvocationTarget: self]
        movePathByX: -offsetX  Y: -offsetY];
    [undoManager setActionName: @"Move"];

    [rawPath offsetPathByX: offsetX  Y: offsetY];

    [[NSNotificationCenter defaultCenter]
        postNotificationName: BWStitchEditController_ChangeNotification
        object: self];
    
    if ([undoManager isUndoing]
        || [undoManager isRedoing]) {
        [stitchCanvas setNeedsDisplay: YES];
    }

} // movePathByX

@end // BWStitchEditController

